<?php
/**
*
*===================================================================
*
*  phpBB Code Repository -- Installer Functions File
*-------------------------------------------------------------------
*	Script info:
* Version:		2.0.0 - "Xerxes" - Alpha 1
* SVN ID:		$Id: install_extras.php 3 2009-07-31 02:25:51Z sTraTosphere.programming $
* Copyright:	(c) 2008, 2009 | Obsidian
* License:		http://opensource.org/licenses/gpl-2.0.php | GNU Public License v2
* Package:		Install
*
*===================================================================
*

*/

if (!defined('IN_INSTALL'))
{
	exit;
}
else
{
	// This is only extra tools, not another module...so we'll cheat, make the installer think it be another module, 
	// and then return once the tools are loaded.
	// This works because return stops script execution, and not processing.  ;)
	return;
}

/**
 * EAMI (Easy Automatic Module Insertion)
 * 
 * @author EXreaction
 * @copyright (c) 2007, 2008 | EXreaction -- http://www.lithiumstudios.org
 * @license http://opensource.org/licenses/gpl-2.0.php | GNU Public License v2
 */
class eami
{
	// Will hold all of the modules
	var $ucp = array();
	var $mcp = array();
	var $acp = array();

	/**
	* Constructor
	*/
	function eami()
	{
		global $db;

		//  Get all of the modules and put them in the data arrays
		$sql = 'SELECT * FROM ' . MODULES_TABLE;
		$result = $db->sql_query($sql);
		while ($row = $db->sql_fetchrow($result))
		{
			$this->{$row['module_class']}[$row['module_id']] = $row;
		}
	}

	/**
	* Add a new module
	*
	* @param string $class The module class, ucp, mcp, acp
	* @param string|int $parent The parent name or parent ID of the module you want to insert
	* @param array $data The data on the module you want to send, like basename/langname/mode/auth/etc.
	*/
	function add_module($class, $parent, $data)
	{
		global $cache, $db;

		if ($class != 'ucp' && $class != 'mcp' && $class != 'acp')
		{
			return false;
		}

		// Here we try to find the parent ID.
		$parent_id = (($parent == '') ? 0 : $parent); // Also accept a blank parent name as the same thing as 0.
		$parent_id = false;
		if (is_numeric($parent) && (intval($parent) == 0 || isset($this->{$class}[intval($parent)])))
		{
			$parent_id = intval($parent);
		}
		else
		{
			foreach ($this->{$class} as $id => $row)
			{
				if (in_array($parent, $row))
				{
					$parent_id = $id;
					break;
				}
			}
		}

		// If we could not find the requested parent, return false
		if ($parent_id === false)
		{
			return false;
		}

		// The left and right ID for the new module
		if ($parent_id != 0)
		{
			$left_id = (int) $this->{$class}[$parent_id]['right_id'];
		}
		else
		{
			$left_id = 0;
			foreach ($this->{$class} as $row)
			{
				if ($row['right_id'] >= $left_id)
				{
					$left_id = $row['right_id'] + 1;
				}
			}
		}
		$right_id = $left_id + 1;

		// Build the module data array which will be inserted into the DB.
		$data = array_merge(array(
			'module_enabled'	=> 1,
			'module_display'	=> 1,
			'module_basename'	=> '',
			'module_class'		=> $class,
			'parent_id'			=> $parent_id,
			'left_id'			=> $left_id,
			'right_id'			=> $right_id,
			'module_langname'	=> '',
			'module_mode'		=> '',
			'module_auth'		=> '',
		), $data);

		// Update the left and right ID's in this classes data
		foreach ($this->{$class} as $id => $row)
		{
			if ($row['left_id'] >= $left_id)
			{
				$this->{$class}[$id]['left_id'] += 2;
			}
			if ($row['right_id'] >= $left_id)
			{
				$this->{$class}[$id]['right_id'] += 2;
			}
		}

		// Update the left and right ID's in the database
		$db->sql_query('UPDATE ' . MODULES_TABLE . ' SET left_id = left_id + 2 WHERE left_id >= ' . $left_id . ' AND module_class = \'' . $class . '\'');
		$db->sql_query('UPDATE ' . MODULES_TABLE . ' SET right_id = right_id + 2 WHERE right_id >= ' . $left_id . ' AND module_class = \'' . $class . '\'');

		// Insert the new module into the DB
		$sql = 'INSERT INTO ' . MODULES_TABLE . ' ' . $db->sql_build_array('INSERT', $data);
		$db->sql_query($sql);
		$module_id = $db->sql_nextid();

		// Make sure to put the new modules' data in this classes data
		$this->{$class}[$module_id] = $data;

		// Clear the Modules Cache
		$cache->destroy("_modules_{$class}");

		return true;
	}
}

/**
* Load a schema (and execute)
*
* @param string $install_path Path to folder containing schema files
* @param mixed $install_dbms Alternative database system than $dbms
*/
function load_schema($install_path = '', $install_dbms = false)
{
	global $db;
	global $table_prefix;

	if ($install_dbms === false)
	{
		global $dbms;
		$install_dbms = $dbms;
	}

	static $available_dbms = false;

	if (!$available_dbms)
	{
		if (!function_exists('get_available_dbms'))
		{
			global $phpbb_root_path, $phpEx;
			include($phpbb_root_path . 'includes/functions_install.' . $phpEx);
		}

		$available_dbms = get_available_dbms($install_dbms);

		if ($install_dbms == 'mysql')
		{
			if (version_compare($db->sql_server_info(true), '4.1.3', '>='))
			{
				$available_dbms[$install_dbms]['SCHEMA'] .= '_41';
			}
			else
			{
				$available_dbms[$install_dbms]['SCHEMA'] .= '_40';
			}
		}
	}

	$remove_remarks = $available_dbms[$install_dbms]['COMMENTS'];
	$delimiter = $available_dbms[$install_dbms]['DELIM'];

	$dbms_schema = $install_path . $available_dbms[$install_dbms]['SCHEMA'] . '_schema.sql';

	if (file_exists($dbms_schema))
	{
		$sql_query = @file_get_contents($dbms_schema);
		$sql_query = preg_replace('#phpbb_#i', $table_prefix, $sql_query);

		$remove_remarks($sql_query);

		$sql_query = split_sql_file($sql_query, $delimiter);

		foreach ($sql_query as $sql)
		{
			$db->sql_query($sql);
		}
		unset($sql_query);
	}

	if (file_exists($install_path . 'schema_data.sql'))
	{
		$sql_query = file_get_contents($install_path . 'schema_data.sql');

		switch ($install_dbms)
		{
			case 'mssql':
			case 'mssql_odbc':
				$sql_query = preg_replace('#\# MSSQL IDENTITY (phpbb_[a-z_]+) (ON|OFF) \##s', 'SET IDENTITY_INSERT \1 \2;', $sql_query);
			break;

			case 'postgres':
				$sql_query = preg_replace('#\# POSTGRES (BEGIN|COMMIT) \##s', '\1; ', $sql_query);
			break;
		}

		$sql_query = preg_replace('#phpbb_#i', $table_prefix, $sql_query);
		$sql_query = preg_replace_callback('#\{L_([A-Z0-9\-_]*)\}#s', 'adjust_language_keys_callback', $sql_query);

		remove_remarks($sql_query);

		$sql_query = split_sql_file($sql_query, ';');

		foreach ($sql_query as $sql)
		{
			$db->sql_query($sql);
		}
		unset($sql_query);
	}
}

/**
* Remove permission options from the list if they exist ... $options is a hash of form ->
* $options = array(
*	'local'		=> array('option1', 'option2', ...),
*	'global'	=> array('optionA', 'optionB', ...)
* );
*/
function remove_permissions($options)
{
	global $auth, $auth_admin, $cache, $db;
	
	// Check to see if $auth_admin class is instantiated...
	$auth_admin_loaded = (class_exists('auth_admin') && is_object($auth_admin)) ? true : false;

	if (!is_array($options))
	{
		return false;
	}
	
	$cur_options = array();

	$sql = 'SELECT auth_option, auth_option_id, is_global, is_local
		FROM ' . ACL_OPTIONS_TABLE . '
		ORDER BY auth_option_id';
	$result = $db->sql_query($sql);

	while ($row = $db->sql_fetchrow($result))
	{
		if ($row['is_global'])
		{
			$cur_options['global'][] = $row['auth_option'];
		}

		if ($row['is_local'])
		{
			$cur_options['local'][] = $row['auth_option'];
		}
	}
	$db->sql_freeresult($result);
	
	// Here we need to check if the options already exist ... this requires discovering whether
	// an options is global, local, or both
	$kill_options = array('local' => array(), 'global' => array());

	foreach ($options as $type => $option_ary)
	{
		$option_ary = array_unique($option_ary);

		foreach ($option_ary as $option_value)
		{
			if (in_array($option_value, $cur_options[$type]))
			{
				$kill_options[$type][] = $option_value;
			}
		}
	}
	unset($options);
	
	$options = array();
	$options['local'] = array_diff($kill_options['local'], $kill_options['global']);
	$options['global'] = array_diff($kill_options['global'], $kill_options['local']);
	$options['local_global'] = array_intersect($kill_options['local'], $kill_options['global']);

	$main_where_sql = '';
	foreach ($options as $type => $option_ary)
	{
		foreach ($option_ary as $option)
		{
			if($main_where_sql != '')
			{
				$main_where_sql .= ' OR ';
			}
			$main_where_sql .= "(auth_option = '" . (string) $option . "'" . ' 
			AND is_global = ' . (($type == 'global' || $type == 'local_global') ? 1 : 0) . '
			AND is_local = ' . (($type == 'local' || $type == 'local_global') ? 1 : 0) . ')';
		}
	}
	
	$sql = 'SELECT auth_option_id
		FROM ' . ACL_OPTIONS_TABLE . '
		WHERE ' . $where_sql . '
			ORDER BY auth_option_id';
	$result = $db->sql_query($sql);

	$where_ids = array();
	
	while ($row = $db->sql_fetchrow($result))
	{
		$where_ids[] = $row['auth_option_id'];
	}
	$db->sql_freeresult($result);
	
	$db->sql_query('DELETE FROM ' . ACL_GROUPS_TABLE . ' WHERE ' . $db->sql_in_set('auth_option_id', $where_ids));
	$db->sql_query('DELETE FROM ' . ACL_ROLES_DATA_TABLE . ' WHERE ' . $db->sql_in_set('auth_option_id', $where_ids));
	$db->sql_query('DELETE FROM ' . ACL_USERS_TABLE . ' WHERE  ' . $db->sql_in_set('auth_option_id', $where_ids));
	$db->sql_query('DELETE FROM ' . ACL_OPTIONS_TABLE . ' WHERE ' . $where_sql);

	$cache->destroy('_acl_options');
	if($auth_admin_loaded)
	{
		$auth_admin->acl_clear_prefetch();
		// Because we just changed the options and also purged the options cache, we instantly update/regenerate it for later calls to succeed.
		$auth_admin->acl_options = array();
		$auth_admin->auth_admin();
	}
	else
	{
		$auth->acl_clear_prefetch();
	}
}

?>